Test source equality when locking dependencies
authorAlex Crichton <alex@alexcrichton.com>
Mon, 24 Nov 2014 01:46:04 +0000 (17:46 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Mon, 24 Nov 2014 01:46:04 +0000 (17:46 -0800)
When applying the lockfile to a resolve graph, we need to take into account that
the listed source of dependencies can change over time, in which case we cannot
lock to the previous version but instead need to continue onwards with updating
the listed source.

Closes #951

src/cargo/core/registry.rs
tests/test_cargo_compile_git_deps.rs

index 39dba008ffc071050de8a69cd9291d60d06e3d0d..ed00428630e8315432a8775fd666138191e4b1ad 100644 (file)
@@ -226,13 +226,30 @@ impl<'a> PackageRegistry<'a> {
         };
         summary.map_dependencies(|dep| {
             match pair {
-                // If this summary has a locked version, then we need to lock
-                // this dependency. If this dependency doesn't have a locked
-                // version, then it was likely an optional dependency which
-                // wasn't included and we just pass it through anyway.
+                // If we've got a known set of overrides for this summary, then
+                // one of a few cases can arise:
+                //
+                // 1. We have a lock entry for this dependency from the same
+                //    source as its listed as coming from. In this case we make
+                //    sure to lock to precisely the given package id.
+                //
+                // 2. We have a lock entry for this dependency, but it's from a
+                //    different source than what's listed. In this case we must
+                //    discard the locked version because the listed source must
+                //    have changed.
+                //
+                // 3. We don't have a lock entry for this dependency, in which
+                //    case it was likely an optional dependency which wasn't
+                //    included previously so we just pass it through anyway.
                 Some(&(_, ref deps)) => {
                     match deps.iter().find(|d| d.get_name() == dep.get_name()) {
-                        Some(lock) => dep.lock_to(lock),
+                        Some(lock) => {
+                            if lock.get_source_id() == dep.get_source_id() {
+                                dep.lock_to(lock)
+                            } else {
+                                dep
+                            }
+                        }
                         None => dep,
                     }
                 }
index 5972630e0b3e7d0d835ed77afeb3f9e8a93bbdc0..dbb846703de20912cccd78f2bc6c7012c4f9c689 100644 (file)
@@ -1563,3 +1563,72 @@ test!(update_one_source_updates_all_packages_in_that_git_source {
     assert!(!lockfile.as_slice().contains(rev1.to_string().as_slice()),
             "{} in {}", rev1, lockfile);
 })
+
+test!(switch_sources {
+    let a1 = git_repo("a1", |project| {
+        project.file("Cargo.toml", r#"
+            [package]
+            name = "a"
+            version = "0.5.0"
+            authors = []
+        "#)
+        .file("src/lib.rs", "")
+    }).assert();
+    let a2 = git_repo("a2", |project| {
+        project.file("Cargo.toml", r#"
+            [package]
+            name = "a"
+            version = "0.5.1"
+            authors = []
+        "#)
+        .file("src/lib.rs", "")
+    }).assert();
+
+    let p = project("project")
+        .file("Cargo.toml", r#"
+            [project]
+            name = "project"
+            version = "0.5.0"
+            authors = []
+            [dependencies.b]
+            path = "b"
+        "#)
+        .file("src/main.rs", "fn main() {}")
+        .file("b/Cargo.toml", format!(r#"
+            [project]
+            name = "b"
+            version = "0.5.0"
+            authors = []
+            [dependencies.a]
+            git = '{}'
+        "#, a1.url()).as_slice())
+        .file("b/src/lib.rs", "fn main() {}");
+
+    p.build();
+    assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
+                execs().with_status(0)
+                       .with_stdout(format!("\
+{updating} git repository `file://[..]a1`
+{compiling} a v0.5.0 ([..]a1#[..]
+{compiling} b v0.5.0 ([..])
+{compiling} project v0.5.0 ([..])
+", updating = UPDATING, compiling = COMPILING).as_slice()));
+
+    File::create(&p.root().join("b/Cargo.toml")).write_str(format!(r#"
+        [project]
+        name = "b"
+        version = "0.5.0"
+        authors = []
+        [dependencies.a]
+        git = '{}'
+    "#, a2.url()).as_slice()).unwrap();
+
+    assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
+                execs().with_status(0)
+                       .with_stdout(format!("\
+{updating} git repository `file://[..]a2`
+{compiling} a v0.5.1 ([..]a2#[..]
+{compiling} b v0.5.0 ([..])
+{compiling} project v0.5.0 ([..])
+", updating = UPDATING, compiling = COMPILING).as_slice()));
+})